<?php

declare(strict_types=1);

namespace App\Controller\Home\User;

use App\Constants\ErrorCode;
use App\Model\Admin\Admin;
use App\Model\Admin\Roles;
use App\Model\BalanceOrder;
use App\Model\Bill;
use App\Model\ChargeDetail;
use App\Model\ChargeOption;
use App\Model\Cooperation;
use App\Model\Coupon;
use App\Model\CouponRecord;
use App\Model\Device;
use App\Model\Distributors;
use App\Model\Feedback;
use App\Model\MainBanner;
use App\Model\Order;
use App\Model\PaymentOrder;
use App\Model\Service;
use App\Model\Station;
use App\Model\User;
use App\Services\AdapayService;
use App\Services\Iot\IotService1 as IotService;
use App\Services\OrderQueueService;
use App\Services\SmsService;
use Hyperf\DbConnection\Db;
use Hyperf\Redis\Redis;
use Hyperf\HttpServer\Contract\RequestInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\SimpleCache\InvalidArgumentException;
use RedisException;
use Trait\ResponseMsg;
use App\Model\Normal;
use Hyperf\Di\Annotation\Inject;
use Util\Common;
use Phper666\JWTAuth\JWT;
use Phper666\JWTAuth\Util\JWTUtil;
use App\Services\Wechat;
use App\Controller\AbstractController;


class UserBalanceOrderController extends AbstractController
{
    use ResponseMsg;

    #[inject]
    protected User $user;
    #[inject]
    protected ChargeOption $chargeOption;
    #[inject]
    protected ChargeDetail $chargeDetail;
    #[inject]
    protected CouponRecord $couponRecord;
    #[inject]
    protected Service $service;
    #[inject]
    protected Order $order;
    #[inject]
    protected AdapayService $adapayService;

    #[inject]
    protected OrderQueueService $orderQueueService;

    #[inject]
    protected Coupon $coupon;

    #[inject]
    protected Device $device;

    protected Redis $redis;
    protected Normal $normal;
    protected JWT $jwt;
    protected Wechat $wechat;

    public function __construct()
    {
        $this->jwt = container()->get(JWT::class);
        $this->redis = container()->get(Redis::class);
        $this->normal = container()->get(Normal::class);
        $this->wechat = container()->get(Wechat::class);
    }

    /**用户充值余额
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function createBalance(RequestInterface $request):ResponseInterface{
        $info = $this->user->getInfo($request);
        if (!$info) {
            return $this->error(code: '400', msg: '登录态失效 请重新登录');
        }
        $params = $request->inputs(['money','sn','pay_type']);
        if($params['sn']){
            $device = $this->device->where('sn',$params['sn'])->first();
            if(!$device){
                return $this->error(1001,'设备编号不存在');
            }
            $save['device_id'] = $device->id;
        }
        $save['number'] =  $this->normal->randOrder($info['id']);
        $save['user_id'] = $info['id'];
        $save['fee']  = $params['money'];
        $save['payment_type'] = $params['pay_type'];
        try{
            $orderModel = BalanceOrder::create($save);
            if(!$orderModel){
                return $this->error(code: '1002', msg: '订单创建失败');
            }
            if($params['pay_type'] == Bill::PAYMENT_TYPE_WE_CHAT_PAY) {
                $expend = ['open_id' => $info['openid']];
                $notifyUrl = Common::MAIN_HOST.'/user/order/balance_notify';
            }else {
                $expend = ['buyer_id' => $info['openid']];
                $notifyUrl = Common::MAIN_HOST.'/user/order/balance_notify';
            }
            $payment_params = array(
                "app_id" => $this->adapayService->appId,
                "order_no" => $orderModel->number,
                "pay_channel" => $params['pay_type'] ,
                "time_expire" => date("YmdHis", time() + 300),
                "pay_amt" =>  sprintf("%.2f", $orderModel->fee),
                "goods_title" => $info['nickname'].'用户充值余额'.$orderModel->fee,
                "goods_desc" =>  $info['nickname'].'用户充值余额'.$orderModel->fee,
                "description" => $info['nickname'].'用户充值余额'.$orderModel->fee,
                "expend" => $expend,
                "notify_url"=>$notifyUrl
            );
            $result = $this->adapayService->Payment($payment_params);
            return $this->success($result);
        }catch (\Exception $e){
            return $this->error(1001,'操作繁忙 请稍后再试');
        }
    }

    /**创建设备订单
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function createOrder(RequestInterface $request):ResponseInterface{
        $params = $request->inputs(['is_autoload','charge_detail_id',
            'charge_option_id','service_id',
            'sn','port','pay_type','coupon_record_id','return_url']);
        $info = $this->user->getInfo($request);
        if (!$info) {
            return $this->error(code: '400', msg: '登录态失效 请重新登录');
        }
        $device = Device::where('sn',$params['sn'])->first();
        if(!$device){
            return $this->error(code: 1001, msg: '设备编号不存在');
        }
        if($device->is_active !=  1 ){
            return $this->error(1001,'设备已暂停服务');
        }
        if($device->inline  != 1){
            return $this->error(1001,'设备已离线');
        }
        $checkUsing = $this->order->where('device_id',$device->id)
            ->where('channel_number',$params['port'])
            ->where('status',$this->order::STATUS_USING)
            ->first();
        if($checkUsing){
            return $this->error(1001,'设备端口正在使用中 请更换其他端口使用');
        }
        $save['device_id'] = $device->id;
        $save['sn']  = $params['sn'];
        $save['payment_type'] = $params['pay_type'];
        $save['channel_number'] = $params['port'];
        $save['station_id'] = $device->station_id;
        $save['is_autoload'] = $params['is_autoload'];
        if($params['is_autoload'] ){
            if(!$params['charge_option_id']){
                return $this->error(1001,'选择充满自停时需要传主套餐id');
            }
            $save['charge_id'] = $params['charge_option_id'];
            $save['minutes'] = 60*12;
            $save['power_fee'] = $save['fee'] = $save['original_fee'] = $this->chargeOption->where('id',$params['charge_option_id'])->value('fee');
        }else{
            $chargeDetailModel = $this->chargeDetail->where('id',$params['charge_detail_id'])->first();
            $save['charge_id'] =  $chargeDetailModel->charge_option_id;
            $save['power_fee'] = $save['fee'] = $save['original_fee'] = $chargeDetailModel->fee;
            $save['minutes'] = 10;
            $save['charge_detail_id'] = $params['charge_detail_id'];
        }
        if($params['coupon_record_id']){
            $couponRecord = $this->couponRecord->where('id',$params['coupon_record_id'])->first();
            if(!$couponRecord){
                return $this->error(1002,'优惠券信息有误');
            }
            if($couponRecord->used_at){
                return $this->error(1002,'优惠券已被使用');
            }
            if(time()>strtotime($couponRecord->expires_at)){
                return $this->error(1002,'优惠券已过期');
            }
            $fillfee = Coupon::where('id',$couponRecord->coupon_id)->value('fee');
            $save['power_fee'] = $save['fee'] = $save['fee']-$fillfee;
            $save['coupon_record_id'] = $params['coupon_record_id'];
        }
        if($params['service_id']){
            $save['service_fee']= $this->service->where('id',$params['service_id'])
             ->value('fee');
            $save['fee'] = $save['fee']+$save['service_fee'];
            $save['service_id'] = $params['service_id'];
        }
        $save['number'] = $this->normal->randOrder($device->id);
        $save['user_id'] = $info['id'];
        try{
            $orderModel = Order::create($save);
            if(!$orderModel){
                return $this->error(code: '1002', msg: '订单创建失败');
            }
            if($params['pay_type'] == Bill::PAYMENT_TYPE_BALANCE){
                $result = $orderModel->balancePay([
                    'return_url' => $params['return_url']
                ]);
                if($result['code'] != 200){
                    return $this->error($result['code'] ,$result['msg']);
                }
                $this->orderQueueService->push($save['number'],6*60);
            }else{
                if($orderModel->fee <= 0){
                    $orderModel->paySuccess();
                    return $this->success(['code'=>200,'msg'=>'成功']);
                }
                if($params['pay_type'] == Bill::PAYMENT_TYPE_WE_CHAT_PAY) {
                    $expend = ['open_id' => $info['openid']];
                    $notifyUrl = Common::MAIN_HOST.'/user/order/wx_notify';
                }else {
                    $expend = ['buyer_id' => $info['openid']];
                    $notifyUrl = Common::MAIN_HOST.'/user/order/ali_notify';
                }
                $payment_params = array(
                    "app_id" => $this->adapayService->appId,
                    "order_no" => $orderModel->number,
                    "pay_channel" => $params['pay_type'] ,
                    "time_expire" => date("YmdHis", time() + 300),
                    "pay_amt" =>  sprintf("%.2f", $orderModel->fee),
                    "goods_title" => $info['nickname'].'用户支付订单'.$orderModel->fee,
                    "goods_desc" =>  '订单设备---'.$device->sn.'-'.$params['port'],
                    "description" => '订单设备---'.$device->sn.'-'.$params['port'],
                    "expend" => $expend,
                    "notify_url"=>$notifyUrl
                );
                $result = $this->adapayService->Payment($payment_params);
            }
            return $this->success($result);
        }catch (\Exception $e){
            return $this->error(1001,'操作繁忙 请稍后再试');
        }
    }

    /**余额充值回调
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function balanceNotify(RequestInterface $request):ResponseInterface{
        $params = $request->all();
        $data = json_decode($params['data'],true);
        $balanceOrder = BalanceOrder::where('number',$data['order_no'])->first();
        $balanceOrder->balanceNotify($data);
        return $this->success();
    }

    public function wxNotify(RequestInterface $request):ResponseInterface{
        $params = $request->all();
        $data = json_decode($params['data'],true);
        $orderModel = $this->order->where('number',$data['order_no'])->first();
        $orderModel->payMent($data);
        if($data['status'] == 'succeeded'){
            $this->orderQueueService->push($data['order_no'],6*60);
        }
        return $this->success();
    }


    public function aliNotify(RequestInterface $request):ResponseInterface{
        $params = $request->all();
        $data = json_decode($params['data'],true);
        $orderModel = $this->order->where('number',$data['order_no'])->first();
        $orderModel->payMent($data);
        if($data['status'] == 'succeeded'){
            $this->orderQueueService->push($data['order_no'],6*60);
        }
        return $this->success();
    }

    /**退款回调
     * @param RequestInterface $request
     * @return void
     */
    public function refund(RequestInterface $request){
        $params = $request->all();
        $data = json_decode($params['data'],true);
        $orderModel = $this->order->where('number',$data['payment_order_no'])->first();
        if($data['status'] == 'succeeded'){
            $orderModel->refundSuccess($params);
        }
    }

    /**我的订单列表
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function myOrderList(RequestInterface $request):ResponseInterface{
        $info = $this->user->getInfo($request);
        if (!$info) {
            return $this->error(code: '400', msg: '登录态失效 请重新登录');
        }
        $page = $request->inputs(['start','end','page','limit','status']);
        $data['list'] = $this->order->where('user_id',$info['id'])
            ->where(function ($query) use ($page) {
                if (array_key_exists('start', $page) && $page['start']) {
                    $query->where('created_at', '>=', $page['start']);
                }
                if (array_key_exists('end', $page) && $page['end']) {
                    $query->where('created_at', '<=', $page['end']);
                }
                if (array_key_exists('status', $page) && $page['status']) {
                    $query->where('status', $page['status']);
                }
            })->offset(($page['page'] - 1) * $page['limit'])
            ->limit($page['limit'])
            ->get(['number','channel_number','sn','station_id','payment_type',
                'estimate_stop_at','stop_at','duration_seconds','device_id',
                'fee','power_fee','service_fee','return_fee','original_fee',
                'out_ord_id','status','is_return_fee','charge_detail_id',
                'charge_id','coupon_record_id','power','stop_reason','is_autoload'])->toArray();
        $data['total'] = $this->order->where('user_id',$info['id'])
            ->where(function ($query) use ($page) {
                if (array_key_exists('start', $page) && $page['start']) {
                    $query->where('created_at', '>=', $page['start']);
                }
                if (array_key_exists('end', $page) && $page['end']) {
                    $query->where('created_at', '<=', $page['end']);
                }
                if (array_key_exists('status', $page) && $page['status']) {
                    $query->where('status', $page['status']);
                }
            })->count();
        foreach($data['list'] as $k => $v ){
            $data['list'][$k]['station'] = Station::where('id',$v['station_id'])->first(['name','address']);
            if($v['charge_detail_id']){
                $data['list'][$k]['chargeDetail'] = $this->chargeDetail->where('id',$v['charge_detail_id'])->first();
            }
            $deviceModel = Device::where('id',$v['device_id'])->first();
            if($deviceModel->child_distributor_id){
                $data['list'][$k]['customer_service_phone'] = Distributors::where('id',$deviceModel->child_distributor_id)->value('customer_service_phone');
            }else{
                $data['list'][$k]['customer_service_phone'] = Distributors::where('id',$deviceModel->distributor_id)->value('customer_service_phone');
            }
        }
        return $this->success($data);
    }

    /**获取套餐详细信息
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function getChargeOrder(RequestInterface $request):ResponseInterface{
        $chargeId = $request->input('charge_id');
        if(!$chargeId){
            return $this->error(1001,'套餐id不能为空');
        }
        $charge = $this->chargeOption->where('id',$chargeId)->first();
        if(!$charge){
            return $this->error(1001,'套餐信息不存在');
        }
        $charge['power_children'] = ChargeDetail::where('charge_option_id',$chargeId)
            ->where('type',ChargeDetail::POWER_TYPE)
            ->orderBy('sort','desc')->get(['id','minutes','min_power','max_power','charge_option_id'])->toArray();
        $charge['time_children'] = ChargeDetail::where('charge_option_id',$chargeId)
            ->where('type',ChargeDetail::TIME_TYPE)
            ->orderBy('sort','desc')->get(['id','minutes','fee','charge_option_id'])->toArray();
        return $this->success($charge);

    }

    /**结束设备充电
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function stopOrder(RequestInterface $request):ResponseInterface{
        $info = $this->user->getInfo($request);
        if (!$info) {
            return $this->error(code: '400', msg: '登录态失效 请重新登录');
        }
        $orderNo = $request->input('order_no');
        if(!$orderNo){
            return $this->error(1001,'订单号不能为空');
        }
        $orderModel = $this->order->where('number',$orderNo)->first();
        if(!$orderModel){
            return $this->error(1001,'订单不存在');
        }
        $iotSn = $this->device->where('id',$orderModel->device_id)->value('iot_sn');
        try{
            IotService::stop($iotSn,$orderModel->channel_number);
            return $this->success();
        }catch (\Exception $e){
            return $this->error(1002,'操作繁忙 请稍后重试');
        }
    }


    /**检查订单状态
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function checkOrderStatus(RequestInterface $request):ResponseInterface{
        $orderNo = $request->input('order_no');
        $orderModel = $this->order->where('number',$orderNo)
            ->first(['id','sn','number','channel_number','duration_seconds',
                'minutes','estimate_stop_at','status','power','is_check']);
        if($orderModel){
            $orderModel->now= date('Y-m-d H:i:s',time());
        }
        return $this->success($orderModel);
    }

    /**反馈建议
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function feedBack(RequestInterface $request):ResponseInterface{
        $info = $this->user->getInfo($request);
        if (!$info) {
            return $this->error(code: '400', msg: '登录态失效 请重新登录');
        }
        $params = $request->inputs(['order_no','name','phone','content','images']);
        if(!$params['order_id']){
            return $this->error(1001,'请选择您要投诉的订单');
        }
        $orderModel = Order::where('id',$params['order_id'])->first();
        $save['order_id'] = $params['order_id'];
        $save['user_id'] = $info['id'];
        $save['name'] = $params['name'];
        $save['phone'] = $params['phone'];
        $save['content'] = $params['content'];
        $save['sn'] =  $orderModel->sn;
        $save['channel_number'] = $orderModel->channel_number;
        $save['images'] = json_encode($params['images']);
        try{
            Feedback::create($save);
            return $this->success(msg:'反馈成功 请等待工作人员处理');
        }catch (\Exception $e){
            return $this->error(1002,'反馈失败 请稍后处理');
        }
    }

    /**反馈订单下拉菜单
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function feedOrderList(RequestInterface $request):ResponseInterface{
        $info = $this->user->getInfo($request);
        if (!$info) {
            return $this->error(code: '400', msg: '登录态失效 请重新登录');
        }
        $oneMonthAgo = date('Y-m-d', strtotime('-1 month'));

        $data = $this->order->where('user_id',$info['id'])
            ->where('created_at','>=',$oneMonthAgo)
            ->get(['number','sn','id','status'])->toArray();
        return $this->success($data);
    }



}
